﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using System.IO;
using System.Reflection;
//using NUnit.Framework.SyntaxHelpers;
using Langexplr.Abc;


namespace AbcLibrary.Tests
{
    [TestFixture]
    public class ClassLoaderTests : BaseClassTestFixture
    {
        [Test]
        public void TestClassNameIdentification()
        {
            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.testclass.abc")))
            {
                AbcFile file = AbcFile.ReadFrom(reader);
                List<AvmClass> classes = new List<AvmClass>();
                for (int i = 0; i < file.Classes.Length; i++)
                {
                    classes.Add(
                        AvmClass.Create((AbcClassInfo)file.Classes.GetValue(i),
                                        (AbcInstanceInfo)file.Instances.GetValue(i),
                                        file.Methods,
                                        file.MethodBodies,
                                        file.ConstantPool,new QualifiedName[]{}));
                }

                Assert.AreEqual(2,classes.Count, "Number of indentified classes");
                Assert.AreEqual("MiPack.BaseMiClase", classes[0].Name.ToString(), "First name");
                Assert.AreEqual("Object", classes[0].SuperClassName.ToString(), "First name parent");
                Assert.AreEqual("MiPack.MiClase", classes[1].Name.ToString(), "Second name");
                Assert.AreEqual("MiPack.BaseMiClase", classes[1].SuperClassName.ToString(), "First name");

            }

        }

        [Test]
        public void TestMethodNameIdentification()
        {
            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.testclass.abc")))
            {                
                List<AvmClass> classes = LoadClass(reader);
 
                
                Assert.AreEqual("MiPack.BaseMiClase", classes[0].Name.ToString(), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");
                
                Assert.AreEqual("Loo", classes[0].Methods.Head.Name.ToString(), "Loo method name");
                Assert.AreEqual("MiPack.MiClase", classes[1].Name.ToString(), "Second name");
                Assert.AreEqual("foo", classes[1].Methods.Head.Name.ToString(), "Loo method name");               
            }
        }

        [Test]
        public void TestMethodReturnTypeIdentification()
        {
           
            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.tc2.abc")))
            {
                List<AvmClass> classes = LoadClass(reader);


                Assert.AreEqual("MiPack.BaseMiClase", classes[0].Name.ToString(), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");

                Assert.AreEqual("int", classes[0].Methods.Head.Method.ReturnType.ToString(), "Loo return type name");
                Assert.AreEqual("MiPack.MiClase", classes[1].Name.ToString(), "Second name");
                Assert.AreEqual("void", classes[1].Methods.Head.Method.ReturnType.ToString(), "Loo return type name");
            }
        }

        [Test]
        public void TestMethodClassReturnTypeIdentification()
        {

            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.EjemploTiposRetorno.abc")))
            {
               
                List<AvmClass> classes = LoadClass(reader);


                Assert.AreEqual("MiPack.BaseMiClase", classes[0].Name.ToString(), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");

                Assert.AreEqual("void", classes[0].Methods.Head.Method.ReturnType.ToString(), "Loo return type name");
                Assert.AreEqual("MiPack.MiClase", classes[1].Name.ToString(), "Second name");
                Assert.AreEqual("MiPack.BaseMiClase", classes[1].Methods.Head.Method.ReturnType.ToString(), "foo return type name");
            }
        }

        [Test]
        public void TestBasicParameterIdentification()
        {
           
            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.PruebaParametros.abc")))
            {

                List<AvmClass> classes = LoadClass(reader);


                Assert.AreEqual("MiPack.MyClass", classes[0].Name.ToString(), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");
                //Assert.AreEqual("miFuncion", classes[0].Methods.Head.Name.ToString(),"Method name");

                AvmMethod method = classes[0].Methods.Head.Method;
                Assert.AreEqual(2, method.Parameters.Length);

                Assert.AreEqual("int", method.Parameters[0].TypeName.ToString());
                Assert.AreEqual("int", method.Parameters[1].TypeName.ToString());

            }
        }


        [Test]
        public void TestOptionalParameterIdentification()
        {

            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.optionalparameters.as3.abc")))
            {

                List<AvmClass> classes = LoadClass(reader);


                Assert.IsTrue(classes[0].Name.ToString().EndsWith(".MyClass"), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");
                Assert.IsTrue( classes[0].Methods.Head.Name.ToString().EndsWith("foo"),"Method name");

                AvmMethod method = classes[0].Methods.Head.Method;
                Assert.AreEqual(1, method.Parameters.Length);

                Assert.AreEqual("int", method.Parameters[0].TypeName.ToString());

                Assert.IsNotNull( method.Parameters[0].OptionalValue.Value);
                Assert.IsTrue(method.Parameters[0].OptionalValue.Value.IsOptionalInt());
                Assert.AreEqual(100,method.Parameters[0].OptionalValue.Value.OptionalInt1);

            }
        }

        [Test]
        public void TestMixedOptionalParameterIdentification()
        {

            using (BinaryReader reader = new BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("AbcLibrary.Tests.files.multipleoptionalparameters.abc")))
            {

                List<AvmClass> classes = LoadClass(reader);


                Assert.IsTrue(classes[0].Name.ToString().EndsWith(".MyClass"), "First name");
                Assert.AreEqual(1, classes[0].Methods.Length, "One method");
                Assert.IsTrue(classes[0].Methods.Head.Name.ToString().EndsWith("foo"), "Method name");

                AvmMethod method = classes[0].Methods.Head.Method;
                Assert.AreEqual(2, method.Parameters.Length);

                Assert.AreEqual("int", method.Parameters[0].TypeName.ToString());

                Assert.AreEqual("int", method.Parameters[1].TypeName.ToString());

                Assert.IsNotNull(method.Parameters[1].OptionalValue.Value);
                Assert.IsTrue(method.Parameters[1].OptionalValue.Value.IsOptionalInt());
                Assert.AreEqual(100, method.Parameters[1].OptionalValue.Value.OptionalInt1);

            }
        }

       
    }
}
